#include <stdio.h>
#include <unistd.h>

#include <cctype>
#include <iostream>
#include <tuple>

#include "muduo/base/Logging.h"
#include "muduo/net/EventLoop.h"
#include "muduo/net/InetAddress.h"
#include "muduo/net/TcpClient.h"
#include "muduo/net/TcpServer.h"
using namespace muduo;
using namespace muduo::net;
using std::string;
EventLoop loop;
string PORT{"9999"};
string DOMAIN{"wangzhengjia.cn"};
std::string message = PORT + DOMAIN;
string get_port(const string& s_port)
{
  int16_t port = stoi(s_port);
  string res_port;
  while (port) {
    res_port.push_back(char(port));
    port >>= 8;
  }
  return {res_port.rbegin(), res_port.rend()};
}
string sizeToString(const string& port, const string& domain);
string sizeToString(const string& port_domain)
{
  int k = -1;
  while (std::isdigit(port_domain[++k]))
    ;
  return sizeToString(port_domain.substr(0, k), port_domain.substr(k));
}
string sizeToString(const string& port, const string& domain)
{
  string res{"\004\001"};
  res.append(get_port(port));
  // #ifndef DEBUG
  //     std::cout << port << "port\n";
  // #endif
  res.push_back('\000');
  res.push_back('\000');
  res.push_back('\000');
  res.push_back('\001');
  res.push_back('\000');
  res += domain;
  res.push_back('\0');
  return res;
}
int i = 0;
void onConnection(const TcpConnectionPtr& conn)
{
  if (conn->connected()) {
    conn->setTcpNoDelay(true);
    std::cout << "establish " << i << std::endl;
    conn->send(sizeToString(message));
  } else {
    printf("onConnection(): connection [%s] is down\n", conn->name().c_str());
  }
}
int cases = 0;
void onMessage(const TcpConnectionPtr& conn, Buffer* buf, Timestamp receiveTime)
{
  cases++;
  printf("onMessage(): received %zd bytes from connection [%s] at %s\n", buf->readableBytes(),
         conn->name().c_str(), receiveTime.toFormattedString().c_str());

  printf("onMessage(): [%s]\n", buf->retrieveAsString(buf->readableBytes()).c_str());
  conn->send("hello " + std::to_string(i));
  if (cases == 2) {
    // conn->shutdown();
    loop.quit();
  }
}

int main(int argc, char** argv)
{
  if (argc > 1) {
    message = argv[1] + DOMAIN;
  }
  InetAddress serverAddr("localhost", 9981);
  for (i = 0; i < 10000; ++i) {
    cases = 0;
    TcpClient client(&loop, serverAddr, std::to_string(i));
    client.setConnectionCallback(onConnection);
    client.setMessageCallback(onMessage);
    client.enableRetry();
    client.connect();
    loop.loop();
  }
}
